package com.qidianit.task.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qidianit.task.mapper.ProjectMapper;
import com.qidianit.task.mapper.TaskMapper;
import com.qidianit.task.pojo.Project;
import com.qidianit.task.service.ProjectService;
import com.qidianit.task.util.Constant;
import com.qidianit.task.util.JSONTools;
import com.qidianit.task.util.ThreadPoolUtil;
import com.qidianit.task.util.pojo.QdResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author 戴着假发的程序员
 * @Company 起点编程
 * @Description
 * @Time 2024/9/5 下午 4:43
 */
@Service
public class ProjectServiceImpl implements ProjectService {
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private TaskMapper taskMapper;
    // 注入Redis的模版类
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    // 注入我们预设的数据key的前缀
    @Value("${project_pre}")
    private String projectPre;
    @Override
    public QdResult queryById(String projectId) {
        String key = projectPre + projectId;
        // 先查询redis
        if(stringRedisTemplate.hasKey(key)){
            String projectJson = stringRedisTemplate.opsForValue().get(key);
            // 将JSON字符串转换为project对象
            try {
                Project project = JSONTools.json2object(projectJson, Project.class);
                // 直接返回
                return QdResult.success(project);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        // 如果程序执行到这里，说明redis中没有数据
        // 从数据库查询
        Project project = projectMapper.selectById(projectId);
        // 把查询的数据给Redis中存储一份
        stringRedisTemplate.opsForValue().set(key,JSONTools.object2json(project));
        // 设置这个key的存活时间. 存活时间设置为一个随机时间。
        stringRedisTemplate.expire(key,30 + new Random().nextInt(30), TimeUnit.MINUTES);
        return QdResult.success(project);
    }
    @Override
    public QdResult selectByPage(Project project, int page, int limit) {
        // 开启分页  参数1： 页码  参数2： 每页大小
        PageHelper.startPage(page,limit);
        // 查询全部
        List<Project> projects = projectMapper.selectList(project);
        String [] projectIds = new String[projects.size()];
        for(int i = 0;i < projects.size();i ++){
            projectIds[i] = projects.get(i).getProjectId();
        }
        List<Map> counts = taskMapper.selectCountByProjects(projectIds);
        for (Project p : projects){
            for (Map map : counts){
                if(map.get("projectId").equals(p.getProjectId())){
                    p.setTaskCount(new Integer(map.get("taskCount").toString()));
                }
            }
        }
        // 创建一个PageInfo对象，构造方法中传入查询的结果集合。
        PageInfo<Project> pageInfo = new PageInfo<>(projects);
        // 将pageInfo对象设置到qdResult中
        return QdResult.success(pageInfo);
    }

    @Override
    public QdResult saveProject(Project project) {
        if(projectMapper.selectById(project.getProjectId()) != null){
            return QdResult.error(Constant.RESPONSE_STATUS_REPEAT,"项目编号重复");
        }
        return projectMapper.insertProject(project) == 1?QdResult.success():QdResult.error();
    }



    @Override
    public QdResult updateById(Project project) {
        String key = projectPre + project.getProjectId();
        // 先删除缓存
        stringRedisTemplate.delete(key);
        // 修改数据
        int result = projectMapper.updateById(project);
        // 等一会再次删除缓存
        // 使用线程池工具类获取线程池对象
        ExecutorService threadPool = ThreadPoolUtil.getThreadPool("projectCacheSubThread");
        // 开启一个线程
        threadPool.submit(()->{
            try {
                int count = 0;
                while (true){
                    Thread.sleep(500);// 等待500毫秒再删除一次
                    try {
                        count ++;
                        stringRedisTemplate.delete(key);
                        break;
                    } catch (Exception e) {
                        // 删除失败就重试！  重试10次。
                    }
                    if(count >= 10){
                        throw new RuntimeException("缓存清理失败!!" + key);
                    }
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        return result == 1?QdResult.success():QdResult.error();
    }

    @Override
    public QdResult archiveById(String projectId) {
        Project project = new Project();
        project.setProjectId(projectId);
        project.setProjectStatus(Constant.DATA_STATUS_ARCHIVE);
        return QdResult.isSuccess(projectMapper.updateById(project));
    }

    @Override
    public QdResult deleteById(String projectId) {
        Project project = new Project();
        project.setProjectId(projectId);
        project.setProjectStatus(Constant.DATA_STATUS_DELETE);
        return QdResult.isSuccess(projectMapper.updateById(project));
    }

    @Override
    public QdResult deletes(String[] ids) {
        return QdResult.success(200,"ok",projectMapper.updateStatusByIds(ids,Constant.DATA_STATUS_DELETE));
    }

    @Override
    public QdResult archives(String[] ids) {
        return QdResult.success(200,"ok",projectMapper.updateStatusByIds(ids,Constant.DATA_STATUS_ARCHIVE));
    }

    @Override
    public QdResult releases(String[] ids) {
        return QdResult.success(200,"ok",projectMapper.updateStatusByIds(ids,Constant.DATA_PROJECT_STATUS_RELEASE));
    }

    @Override
    public QdResult queryDeletes(Project project,int page,int limit) {
        // 开启分页  参数1： 页码  参数2： 每页大小
        PageHelper.startPage(page,limit);
        // 查询全部
        List<Project> projects = projectMapper.selectDeletes(project);
        // 创建一个PageInfo对象，构造方法中传入查询的结果集合。
        PageInfo<Project> pageInfo = new PageInfo<>(projects);
        // 将pageInfo对象设置到qdResult中
        return QdResult.success(pageInfo);
    }

    @Override
    public QdResult reReleases(String[] ids) {
        return QdResult.success(200,"ok",projectMapper.updateStatusByIds(ids,Constant.DATA_PROJECT_STATUS_RELEASE));
    }

    @Override
    public QdResult reDrafts(String[] ids) {
        return QdResult.success(200,"ok",projectMapper.updateStatusByIds(ids,Constant.DATA_STATUS_NORMAL));
    }
}
